﻿using System.Linq.Expressions;
using Mapster;
using SqlSugar;
using Vin.Extension.Framework.Base;
using Vin.Extension.Framework.Dto;
using Vin.Extension.Framework.Entities;
using Vin.Extension.Framework.Extension;
using Vin.Extension.Framework.Interface;
using Vin.Extension.Framework.Repository;
using Vin.Tool.Attributes;

namespace Vin.Extension.Framework.Implement;

public class
    VinFrameworkBaseRecordEntityServiceAsync<TEntity, TEntityListDto, TBaseRepository> :
    VinFrameworkBaseService,
    IVinFrameworkBaseRecordEntityServiceAsync<TEntity, TEntityListDto>
    where TEntity : VinFrameworkBaseRecordEntity, new()
    where TEntityListDto : VinFrameworkBaseListDto, new()
    where TBaseRepository : class, IVinFrameworkBaseRecordRepository<TEntity>
{
    [Inject] protected readonly TBaseRepository _baseRepository = null!;

    public virtual Expressionable<TEntity> CreateExpressionable(
        Expression<Func<TEntity, bool>>? expression = null)
    {
        return Expressionable.Create<TEntity>()
            .AndIF(expression != null, expression);
    }

    public virtual async Task<List<T>> ListAsync<T>(TEntityListDto dto,
        Expressionable<TEntity>? whereExpression = null, bool notPage = false)
    {
        var queryable = _baseRepository.AsQueryable();
        if (whereExpression != null)
        {
            queryable.Where(whereExpression.ToExpression());
        }

        return (await queryable.ToPageListRecordAsync(dto, notPage: notPage)).Adapt<List<T>>();
        // return queryable.ToPageListRecordAsync(dto, notPage: notPage);
        // var list = await _baseRepository.AsQueryable().ToPageListRecordAsync(dto, notPage: notPage);
        // return (await _baseRepository.AsQueryable()
        //     .WhereIF(whereExpression != null, whereExpression!.ToExpression())
        //     .ToPageListRecordAsync(dto, notPage: notPage)).Adapt<List<T>>();
    }

    public async Task<List<TEntity>> ListAsync(TEntityListDto dto,
        Expressionable<TEntity> whereExpression)
    {
        return await ListAsync<TEntity>(dto, whereExpression);
    }

    public virtual async Task<List<TEntity>> ListAsync(TEntityListDto dto)
    {
        return await ListAsync<TEntity>(dto);
    }

    public virtual async Task<List<T>> ListAllAsync<T>(TEntityListDto dto, bool checkEnabled = true)
    {
        var whereExpression = Expressionable.Create<TEntity>()
            .AndIF(checkEnabled, m => m.IsEnabled == true);
        return await ListAsync<T>(dto, whereExpression, true);
    }

    public virtual async Task<List<TEntity>> ListAllAsync(TEntityListDto dto, bool checkEnabled = true)
    {
        return await ListAllAsync<TEntity>(dto, checkEnabled);
    }

    public virtual async Task<T?> QueryAsync<T>(long id)
    {
        return (await _baseRepository.GetFirstAsync(m => m.Id == id)).Adapt<T?>();
    }

    public virtual async Task<TEntity?> QueryAsync(long id)
    {
        return (await _baseRepository.GetFirstAsync(m => m.Id == id));
    }

    public virtual async Task<TEntity?> SaveReturnDataAsync(TEntity entity)
    {
        return (await _baseRepository.SaveOrUpdateAsync(entity));
    }

    public async Task<TEntity?> SaveReturnDataAsync(TEntity entity, Func<TEntity, Task>? insertCallback,
        Func<TEntity, Task>? updateCallback = null)
    {
        return (await _baseRepository.SaveOrUpdateAsync(entity, insertCallback, updateCallback))
            .Adapt<TEntity>();
    }

    public async Task<TEntity?> SaveReturnDataAsync(TEntity entity,
        Func<SaveType, TEntity, Task> saveCallback)
    {
        return (await _baseRepository.SaveOrUpdateAsync(entity, saveCallback))
            .Adapt<TEntity>();
    }

    public virtual async Task<bool> SaveAsync(TEntity entity)
    {
        return await SaveReturnDataAsync(entity) != null;
    }

    public async Task<bool> SaveAsync(List<TEntity> entities)
    {
        return await _baseRepository.InsertRangeAsync(entities, true);
    }

    public virtual async Task<bool> DelAsync(long id)
    {
        return await _baseRepository.LogicDeleteAsync(m => m.Id == id);
    }

    public virtual async Task<bool> EnabledAsync(long id, bool? enabled)
    {
        if (!enabled.HasValue) return false;
        return await SaveAsync(new TEntity()
        {
            Id = id,
            IsEnabled = enabled,
        });
    }


    public (List<TEntity>, List<TEntity>, List<TEntity>) Compare(
        List<TEntity> newDtoList, List<TEntity> newList)
    {
        return _baseRepository.Compare(newDtoList, newList);
    }
}